using System;

namespace Aima.Core.Util.math
{
    /**
     * Basic supports for Intervals.
     * see http://en.wikipedia.org/wiki/Interval_%28mathematics%29
     **/

    public class Interval<TC>
    {
        private IComparable<TC> _lower;
        private bool _lowerInclusive = true;
        private IComparable<TC> _upper;
        private bool _upperInclusive = true;

        public Interval()
        {
        }

        // Constructs a closed interval from the two specified end points.
        public Interval(IComparable<TC> lower, IComparable<TC> upper)
        {
            Lower =lower;
            Upper = upper;
        }

        // Constructs an interval from the two specified end points.
        public Interval(IComparable<TC> lower, bool lowerInclusive,
                        IComparable<TC> upper, bool upperInclusive)
        {
            Lower = lower;
            IsLowerInclusive = lowerInclusive;
            Upper= upper;
            IsUpperInclusive=upperInclusive;
        }

       // Returns true if the specified object is between the end points of this interval.
         
        public bool IsInInterval(TC o)
        {
            if (null == _lower || null == _upper) return false;


            bool isIn = IsLowerInclusive ? _lower.CompareTo(o) <= 0 : _lower.CompareTo(o) < 0;

            if (isIn)
            {
                isIn = IsUpperInclusive ? _upper.CompareTo(o) >= 0 : _upper.CompareTo(o) > 0;
            }

            return isIn;
        }
        
        public bool IsLowerInclusive
        { 
            get{ return _lowerInclusive; }
            set { _lowerInclusive = value; }
        }


        // TODO: not sure I like this IsLowerExclusive toggle property
        public bool IsLowerExclusive
        {
            get{return ! _lowerInclusive;}
            set { _lowerInclusive = !value; }
        }

       

        public IComparable<TC> Lower
        {
            get { return _lower; }
            set { _lower = value; }
        }

        public bool IsUpperInclusive
        {
            get { return _upperInclusive; }
            set { _upperInclusive = value; }
        }

        

        public bool IsUpperExclusive
        {
            get { return !_upperInclusive; }
            set { _upperInclusive = !value; }
        }

        

        public IComparable<TC> Upper
        {
            get { return _upper; }
            set { _upper = value; }
        }

       
        public override String ToString()
        {
            return (_lowerInclusive ? "[" : "(") + _lower + ", " + _upper
                   + (_upperInclusive ? "]" : ")");
        }
    }
}